//
// Created by ChenJi on 2021/4/13.
//
#include "data_center.h"
#include "rtc_extern.h"
#include "string_library.h"
#include "TastekE16.h"

char *DATA_CENTER_HEADER = "[DataCenter]";
uint16_t now_index;
Warner_Event event_buf;
uint8_t index_buf[2];
uint8_t data_buffer[11];
uint8_t pocket_send_event[4] = {0xEE, 0xA1, 0x00, 0xFE};
uint8_t num_buf[20];
struct config {
    uint8_t isConfigSetted;
    uint8_t enable_auto_set;
    uint8_t start_h;
    uint8_t start_m;
    uint8_t start_s;
    uint8_t end_h;
    uint8_t end_m;
    uint8_t end_s;
    uint8_t is_Defeating;
} cfg;


void loadConfig() {
    readConfig();
    if (cfg.isConfigSetted != 0xFA) {
        data_center_debug_sync("Config has not been initialized");
        data_center_debug_sync_process("resetting the config.... ");
        resetConfig();
        data_center_debug_sync_process_done();
        data_center_debug_sync_process("saving the config.... ");
        saveConfig();
        data_center_debug_sync_process_done();
        readConfig();
    } else {
        data_center_debug_sync("Config has been initialized");
    }
    data_center_debug_sync("-------------------------------CONFIG_INFO--------------------------------");
    print_config_information("is configured", cfg.isConfigSetted, 0, 1);
    print_config_information("is auto set enabled", cfg.is_Defeating, 0, 1);
    print_config_information("is auto set enabled", cfg.enable_auto_set, 0, 1);
    print_config_information("auto set start hour", cfg.start_h, 10, 0);
    print_config_information("auto set start minute", cfg.start_m, 10, 0);
    print_config_information("auto set start second", cfg.start_s, 10, 0);
    print_config_information("auto set end hour", cfg.end_h, 10, 0);
    print_config_information("auto set end minute", cfg.end_m, 10, 0);
    print_config_information("auto set end second", cfg.end_s, 10, 0);
    data_center_debug_sync("------------------------------------------------------------------------");
}

void readConfig() {
    SPI_W25X_Read((uint8_t *) &cfg, 0x600000, 9);
}

void saveConfig() {
    SPI_W25X_Write((uint8_t *) &cfg, 0x600000, 9);
}


void resetConfig() {
    cfg.isConfigSetted = 0xFA;
    cfg.enable_auto_set = 0;
    cfg.start_h = 0;
    cfg.start_m = 0;
    cfg.start_s = 0;
    cfg.end_h = 0;
    cfg.end_m = 0;
    cfg.end_s = 0;
    cfg.is_Defeating = 0;
}

void setStartTime(uint8_t h, uint8_t m, uint8_t s) {
    cfg.start_m = m;
    cfg.start_h = h;
    cfg.start_s = s;
    saveConfig();
}

void setEndTime(uint8_t h, uint8_t m, uint8_t s) {
    cfg.end_m = m;
    cfg.end_h = h;
    cfg.end_s = s;
    saveConfig();
}

void getStartTime(uint8_t *data) {
    *data = cfg.start_h;
    *(data + 1) = cfg.start_m;
    *(data + 2) = cfg.start_s;
}

void getEndTime(uint8_t *data) {
    *data = cfg.end_h;
    *(data + 1) = cfg.end_m;
    *(data + 2) = cfg.end_s;
}

void enableAutoSet() {
    cfg.enable_auto_set = 1;
    saveConfig();
}

uint8_t isAutoSetMode() {
    return cfg.enable_auto_set;
}

void disableAutoSet() {
    cfg.enable_auto_set = 0;
    saveConfig();
}

void enableDefeatState() {
    cfg.is_Defeating = 1;
}

void disableDefeatState() {
    cfg.is_Defeating = 0;
    saveConfig();
}

void data_center_debug_sync(char *data) {
    debug_sync(DATA_CENTER_HEADER);
    debug_sync(data);
    debug_sync("\n");
}

void data_center_debug_sync_process(char *data) {
    debug_sync(DATA_CENTER_HEADER);
    debug_sync(data);
}

void data_center_debug_sync_process_done() {
    debug_sync("Done\n");
}

void data_center_print_number(int32_t number) {
    myitoa(number, num_buf, 10);
    debug_sync(num_buf);
}

void print_config_information(char *inf_name, uint32_t value, uint8_t radix, uint8_t is_bool) {
    debug_sync(DATA_CENTER_HEADER);
    debug_sync(inf_name);
    uint8_t len = 40 - mystr_len(inf_name);
    for (uint8_t i = 0; i < len; i++)debug_sync(" ");
    debug_sync(" : ");
    if (is_bool)
        debug_sync(value ? "True" : "False");
    else {
        myitoa(value, num_buf, radix);
        debug_sync(num_buf);
    }
    debug_sync("\n");
}

void data_center_print_number_hex(int32_t number) {
    myitoa(number, num_buf, 16);
    debug_sync(num_buf);
}

Warner_Event *addEvent(uint8_t event_type) {
    return setEvent(now_index, event_type);
}

uint16_t getIndex() {
    return now_index;
}

void saveEvent(Warner_Event *event) {
    uint8_t i = 0;
    data_buffer[i++] = 0xFA;
    data_buffer[i++] = (uint8_t) event->id >> 8;
    data_buffer[i++] = (uint8_t) event->id;
    data_buffer[i++] = event->year;
    data_buffer[i++] = event->month;
    data_buffer[i++] = event->day;
    data_buffer[i++] = event->hour;
    data_buffer[i++] = event->minute;
    data_buffer[i++] = event->second;
    data_buffer[i++] = event->event_type;
    data_buffer[i++] = event->synchronized;
    SPI_W25X_Write(data_buffer, getWarnerEventAddress(event->id), 11);
}

Warner_Event *setEvent(uint16_t event_id, uint8_t event_type) {
    event_buf.id = event_id;
    event_buf.event_type = event_type;
    TIME_STAMP *time = getCurrentTimeSTAMP();
    event_buf.year = time->year;
    event_buf.month = time->month;
    event_buf.day = time->day;
    event_buf.hour = time->hour;
    event_buf.minute = time->minute;
    event_buf.second = time->second;
    event_buf.synchronized = 0;
    saveEvent(&event_buf);
    now_index++;
    setIndex(now_index);
    return &event_buf;
}

void setIndex(uint16_t index) {
    index_buf[0] = index >> 8;
    index_buf[1] = index;
    debug("[DEBUG]Index Saved\n");
    SPI_W25X_Write(index_buf, INDEX_ADDRESS, 2);
}

void system_logger_init() {
    loadIndex();
}

void loadIndex() {
    uint8_t H = SPI_W25X_Read_onebyte(INDEX_ADDRESS);
    uint8_t L = SPI_W25X_Read_onebyte(INDEX_ADDRESS + 1);
    now_index = (H << 8 | L);
}

uint8_t containEvent(uint16_t index) {
    return SPI_W25X_Read_onebyte(getWarnerEventAddress(index)) == 0xFA;
}

uint8_t *getOriginEventData(uint16_t index) {
    if (SPI_W25X_Read_onebyte(getWarnerEventAddress(index)) != 0xFA) {
        data_buffer[3] = 255;
        return data_buffer;
    }
    SPI_W25X_Read(data_buffer, getWarnerEventAddress(index), 11);
    return data_buffer;
}

Warner_Event *readEvent(uint16_t index) {
    if (SPI_W25X_Read_onebyte(getWarnerEventAddress(index)) != 0xFA) {
        event_buf.event_type = 255;
        return &event_buf;
    }
    SPI_W25X_Read(data_buffer, getWarnerEventAddress(index), 11);
    uint8_t i = 3;
    event_buf.id = data_buffer[1] << 8 & data_buffer[2];
    event_buf.year = data_buffer[i++];
    event_buf.month = data_buffer[i++];
    event_buf.day = data_buffer[i++];
    event_buf.hour = data_buffer[i++];
    event_buf.minute = data_buffer[i++];
    event_buf.second = data_buffer[i++];
    event_buf.event_type = data_buffer[i++];
    event_buf.synchronized = data_buffer[i++];
    return &event_buf;
}

void sendEventToServer(uint8_t event_id) {
    pocket_send_event[2] = event_id;
    sendRemoteCommand(pocket_send_event, 4);
}

uint8_t chengeSyncState(uint8_t mode, uint16_t id) {
    if (!containEvent(id)) { return 0; }
    SPI_W25X_Write_onebyte(getWarnerEventSyncAddress(id), mode);
}

void listLog() {
    uint8_t data[6];
    for (uint16_t i = 0; i <= now_index; i++) {
        debug_sync("[SYSTEM Logger]ID: ");
        myitoa(i, data, 10);
        debug_sync(data);
        if (SPI_W25X_Read_onebyte(getWarnerEventAddress(i)) != 0xFA) {
            event_buf.event_type = 255;
            debug_sync(" Error:Bad_Data \n");
            continue;
        }
        SPI_W25X_Read(data_buffer, getWarnerEventAddress(i), 11);
        debug_sync("  TIME: ");
        myitoa(data_buffer[3], data, 10);
        debug_sync(data);
        debug_sync("-");
        myitoa(data_buffer[4], data, 10);
        debug_sync(data);
        debug_sync("-");
        myitoa(data_buffer[5], data, 10);
        debug_sync(data);
        debug_sync(" ");
        myitoa(data_buffer[6], data, 10);
        debug_sync(data);
        debug_sync(":");
        myitoa(data_buffer[7], data, 10);
        debug_sync(data);
        debug_sync(":");
        myitoa(data_buffer[8], data, 10);
        debug_sync(data);
        debug_sync("  EventID: ");
        myitoa(data_buffer[9], data, 10);
        debug_sync(data);
        //   debug_sync(data_buffer[10] ? "  Synced" : "  NOT synced");
        debug_sync("\n");
    }
}